#ifndef __PTGUI_OBJECT_H__
#define __PTGUI_OBJECT_H__


#ifdef __cplusplus
extern "C"
{
#endif

/* ptgui object type */

/** Casts the function pointer to an ptgui_constructor */
#define PTGUI_CONSTRUCTOR(constructor)  			  ((ptgui_constructor_t)(constructor))
/** Casts the function pointer to an ptgui_constructor */
#define PTGUI_DESTRUCTOR(destructor)				  ((ptgui_destructor_t)(destructor))

/* pre-definetion */
struct ptgui_object;
typedef struct ptgui_object ptgui_object_t;
typedef void (*ptgui_constructor_t)(ptgui_object_t *object);
typedef void (*ptgui_destructor_t)(ptgui_object_t *object);

/* ptgui type structure */
struct ptgui_type
{
	/* type name */
	rt_char_t			*name;

	/* hierarchy and depth */
	struct ptgui_type	**hierarchy;
	rt_int8_t			hierarchy_depth;

	/* constructor and destructor */
	ptgui_constructor_t	constructor;
	ptgui_destructor_t	destructor;

	/* size of type */
	rt_int16_t			size;
};
typedef struct ptgui_type ptgui_type_t;

ptgui_type_t *ptgui_type_create(const rt_char_t *type_name, ptgui_type_t *parent_type, rt_int16_t type_size,
								ptgui_constructor_t constructor, ptgui_destructor_t destructor);
void ptgui_type_destroy(ptgui_type_t *type);

void ptgui_type_object_construct(ptgui_type_t *type, ptgui_object_t *object);
void ptgui_type_destructors_call(ptgui_type_t *type, ptgui_object_t *object);
rt_bool_t ptgui_type_inherits_from(ptgui_type_t *type, ptgui_type_t *parent);
ptgui_type_t *ptgui_type_parent_type_get(ptgui_type_t *type);
const rt_char_t *ptgui_type_name_get(ptgui_type_t *type);
ptgui_type_t *ptgui_type_get_from_name(const rt_char_t *name);

#ifdef PTGUI_USING_CAST_CHECK
#define PTGUI_OBJECT_CAST(obj, ptgui_type_t, c_type) \
((c_type *)ptgui_object_check_cast((ptgui_object_t *)(obj), (ptgui_type_t)))
#else
#define PTGUI_OBJECT_CAST(obj, ptgui_type_t, c_type)	 ((c_type *)(obj))
#endif

#define PTGUI_OBJECT_CHECK_TYPE(_obj, _type) \
(ptgui_type_inherits_from(((ptgui_object_t *)(_obj))->type, (_type)))

/** Gets the type of an object */
#define PTGUI_OBJECT_TYPE   	(ptgui_object_type_get())
/** Casts the object to an ptgui_object_t */
#define PTGUI_OBJECT(obj)   	(PTGUI_OBJECT_CAST((obj), PTGUI_OBJECT_TYPE, ptgui_object_t))
/** Checks if the object is an ptgui_Object */
#define PTGUI_IS_OBJECT(obj)	(PTGUI_OBJECT_CHECK_TYPE((obj), PTGUI_OBJECT_TYPE))

/* ptgui base object */
struct ptgui_object
{
	/* object type */
	ptgui_type_t *type;

	rt_bool_t	is_static;
};

ptgui_type_t *ptgui_object_type_get(void);

ptgui_object_t *ptgui_object_create(ptgui_type_t *object_type);
void ptgui_object_destroy(ptgui_object_t *object);

void ptgui_object_name_set(ptgui_object_t *object, const rt_int8_t *name);
const rt_int8_t *ptgui_object_name_get(ptgui_object_t *object);

ptgui_object_t *ptgui_object_check_cast(ptgui_object_t *object, ptgui_type_t *type);
ptgui_type_t *rtk_object_object_type_get(ptgui_object_t *object);

#ifdef __cplusplus
}
#endif

#endif
